//
//  JiepaiViewController.swift
//  Duyiguqin
//
//  Created by 张昭 on 2024/8/11.
//

import UIKit
import Alamofire
import AVFoundation

class JiepaiViewController: BaseViewController {
    
    deinit {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        debugPrint("JiepaiViewController init")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        for url in App.shared.cachedMusics.values {
            cachedPlayerItems[url] = AVPlayerItem(url: url)
        }
        initializeSubviews()
        setDefaultConfig()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
        requestData()
    }
    
    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        beatBgView.snp.updateConstraints { make in
            make.bottom.equalTo(-max(view.safeAreaInsets.bottom, 20))
        }
        offsetY = view.safeAreaInsets.top + 44
        showBeats(num: beatsCount)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touchPoint = touches.first?.location(in: view) else { return }
        guard !textFieldBgView.frame.contains(touchPoint) else { return }
        view.endEditing(true)
    }
    
    private lazy var bgView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        return v
    }()
    
    private lazy var startButton: UIButton = {
        let v = UIButton(type: .custom)
        v.setBackgroundImage(UIImage(resource: .jiepaiStart), for: .normal)
        v.setTitle("START", for: .normal)
        v.setTitle("END", for: .selected)
        v.setTitleColor(UIColor(0xD3C390), for: .normal)
        v.titleLabel?.font = UIFont.systemFont(ofSize: 40, weight: .bold)
        v.addTarget(self, action: #selector(onClickStartButton(_:)), for: .touchUpInside)
        return v
    }()
    
    private lazy var beatBgView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        v.layer.shadowColor = UIColor.black.cgColor
        v.layer.shadowOpacity = 0.05
        v.layer.shadowOffset = CGSize(width: 0, height: 5)
        v.layer.shadowRadius = 15
        v.layer.cornerRadius = 12
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        label.textColor = UIColor(0x0F0F0F)
        label.text = "节拍"
        v.addSubview(label)
        label.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.centerY.equalTo(24)
        }
        return v
    }()
    
    private lazy var beatButton: UIButton = {
        let v = UIButton(type: .custom)
        v.backgroundColor = UIColor(0xF2F2F2)
        v.layer.cornerRadius = 12
        v.layer.masksToBounds = true
        v.addTarget(self, action: #selector(onClickBeatButton(_:)), for: .touchUpInside)
        v.setTitleColor(UIColor(0x0F0F0F), for: .normal)
        v.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        return v
    }()
    
    private lazy var beatLeftLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        v.textColor = UIColor(0x0F0F0F)
        v.textAlignment = .right
        return v
    }()
    
    private lazy var beatMiddleView: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(0x0F0F0F)
        return v
    }()
    
    private lazy var beatRightLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        v.textColor = UIColor(0x0F0F0F)
        v.textAlignment = .left
        return v
    }()
    
    private lazy var tempoBgView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        v.layer.shadowColor = UIColor.black.cgColor
        v.layer.shadowOpacity = 0.05
        v.layer.shadowOffset = CGSize(width: 0, height: 5)
        v.layer.shadowRadius = 15
        v.layer.cornerRadius = 12
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        label.textColor = UIColor(0x0F0F0F)
        label.text = "速度(BPM)"
        v.addSubview(label)
        label.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.centerY.equalTo(24)
        }
        return v
    }()
    
    private lazy var tempoButton: UIButton = {
        let v = UIButton(type: .custom)
        v.backgroundColor = UIColor(0xF2F2F2)
        v.layer.cornerRadius = 12
        v.layer.masksToBounds = true
        v.addTarget(self, action: #selector(onClickTempoButton(_:)), for: .touchUpInside)
        v.setTitleColor(UIColor(0x0F0F0F), for: .normal)
        v.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        return v
    }()
    
    private lazy var jianTempoButton: UIButton = {
        let v = UIButton(type: .custom)
        v.setImage(UIImage(resource: .jiepaiJian), for: .normal)
        v.contentEdgeInsets = UIEdgeInsets(top: 10, left: 6.5, bottom: 10, right: 0)
        v.addTarget(self, action: #selector(onClickJianTempoButton(_:)), for: .touchUpInside)
        return v
    }()
    
    private lazy var jiaTempoButton: UIButton = {
        let v = UIButton(type: .custom)
        v.setImage(UIImage(resource: .jiepaiJia), for: .normal)
        v.contentEdgeInsets = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 6.5)
        v.addTarget(self, action: #selector(onClickJiaTempoButton(_:)), for: .touchUpInside)
        return v
    }()
    
    private lazy var instrumentBgView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        v.layer.shadowColor = UIColor.black.cgColor
        v.layer.shadowOpacity = 0.05
        v.layer.shadowOffset = CGSize(width: 0, height: 5)
        v.layer.shadowRadius = 15
        v.layer.cornerRadius = 12
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        label.textColor = UIColor(0x0F0F0F)
        label.text = "乐器"
        v.addSubview(label)
        label.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.centerY.equalTo(24)
        }
        return v
    }()
    
    private lazy var insctrumentButton: UIButton = {
        let v = UIButton(type: .custom)
        v.backgroundColor = UIColor(0xF2F2F2)
        v.layer.cornerRadius = 12
        v.layer.masksToBounds = true
        v.addTarget(self, action: #selector(onClickInstrumentButton(_:)), for: .touchUpInside)
        v.setTitleColor(UIColor(0x0F0F0F), for: .normal)
        v.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
        return v
    }()
    
    private lazy var textFieldBgView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        v.layer.shadowColor = UIColor.black.cgColor
        v.layer.shadowOpacity = 0.05
        v.layer.shadowOffset = CGSize(width: 0, height: 5)
        v.layer.shadowRadius = 15
        v.layer.cornerRadius = 10
        return v
    }()
    
    private lazy var textField: UITextField = {
        let v = UITextField()
        v.keyboardType = .numberPad
        v.delegate = self
        return v
    }()
    
    private lazy var textFieldConfirmButton: UIButton = {
        let v = UIButton(type: .custom)
        v.setTitle("确定", for: .normal)
        v.setTitleColor(UIColor(0xD3C390), for: .normal)
        v.setTitleColor(UIColor(0xD3C390).withAlphaComponent(0.6), for: .highlighted)
        v.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: .bold)
        v.addTarget(self, action: #selector(onClickTextFieldConfirmButton(_:)), for: .touchUpInside)
        return v
    }()
    
    private var beatsView: [UIView] = []
    
    private var beatsCount: Int = 16
    
    private var offsetY: CGFloat = 44
    
    private var timer: ZZTimer?
    
    private var timeCounter: Int = -1
    
    private var currentTempo: Int = 60 {
        didSet {
            tempoButton.setTitle("\(currentTempo)", for: .normal)
            if startButton.isSelected {
                startTimer()
            }
        }
    }
    
    private var beatLeftValue: Int = 2 {
        didSet {
            beatLeftLabel.text = "\(beatLeftValue)"
            showBeats(num: beatLeftValue)
        }
    }
    
    private var beatRightValue: Int = 2 {
        didSet {
            beatRightLabel.text = "\(beatRightValue)"
        }
    }
    
    private var cachedPlayerItems: [URL: AVPlayerItem] = [:]
    private var instruments: [Instrument] = []
    private var selectedInstrument: Instrument? {
        didSet {
            guard let ins = selectedInstrument else { return }
            insctrumentButton.setTitle(ins.name, for: .normal)
            if let url = App.shared.cachedMusics[ins.url] {
                if let item = cachedPlayerItems[url] {
                    player.replaceCurrentItem(with: item)
                } else {
                    let item = AVPlayerItem(url: url)
                    cachedPlayerItems[url] = item
                    player.replaceCurrentItem(with: item)
                }
            } else {
                let item = AVPlayerItem(url: ins.url)
                cachedPlayerItems[ins.url] = item
                player.replaceCurrentItem(with: item)
            }
        }
    }
    
    private let player = AVPlayer()
}

extension JiepaiViewController {
    
    private func initializeSubviews() {
        
        titleLabel.text = "度一节拍器"
        
        view.addSubview(bgView)
        bgView.snp.makeConstraints { make in
            make.left.right.bottom.equalTo(0)
            make.top.equalTo(naviHeaderView.snp.bottom)
        }
        
        for _ in 0..<16 {
            let btn = UIView()
            btn.backgroundColor = .white
            btn.layer.shadowColor = UIColor.black.cgColor
            btn.layer.shadowOpacity = 0.05
            btn.layer.shadowOffset = CGSize(width: 0, height: 5)
            btn.layer.shadowRadius = 15
            btn.layer.cornerRadius = 12
            view.addSubview(btn)
            btn.isHidden = true
            beatsView.append(btn)
        }
        
        view.addSubview(startButton)
        startButton.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.size.equalTo(240)
            make.top.equalTo(naviHeaderView.snp.bottom).offset(240)
        }
        
        view.addSubview(beatBgView)
        beatBgView.snp.makeConstraints { make in
            make.left.equalTo(15)
            make.size.equalTo(95)
            make.bottom.equalTo(-max(view.safeAreaInsets.bottom, 20))
        }
        
        beatBgView.addSubview(beatButton)
        beatButton.snp.makeConstraints { make in
            make.height.equalTo(30)
            make.left.equalTo(10)
            make.right.equalTo(-10)
            make.bottom.equalTo(-18)
        }
        
        beatBgView.addSubview(beatMiddleView)
        beatMiddleView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.height.equalTo(14)
            make.width.equalTo(1)
            make.centerY.equalTo(beatButton)
        }
        
        beatBgView.addSubview(beatLeftLabel)
        beatLeftLabel.snp.makeConstraints { make in
            make.right.equalTo(beatMiddleView.snp.left).offset(-5)
            make.centerY.equalTo(beatButton)
        }
        
        beatBgView.addSubview(beatRightLabel)
        beatRightLabel.snp.makeConstraints { make in
            make.left.equalTo(beatMiddleView.snp.right).offset(5)
            make.centerY.equalTo(beatButton)
        }
        
        view.addSubview(tempoBgView)
        tempoBgView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.size.equalTo(95)
            make.top.equalTo(beatBgView)
        }
        
        tempoBgView.addSubview(tempoButton)
        tempoButton.snp.makeConstraints { make in
            make.height.equalTo(30)
            make.left.equalTo(10)
            make.right.equalTo(-10)
            make.bottom.equalTo(-18)
        }
        
        tempoBgView.addSubview(jianTempoButton)
        jianTempoButton.snp.makeConstraints { make in
            make.left.equalTo(tempoButton)
            make.centerY.equalTo(tempoButton)
        }
        
        tempoBgView.addSubview(jiaTempoButton)
        jiaTempoButton.snp.makeConstraints { make in
            make.right.equalTo(tempoButton)
            make.centerY.equalTo(tempoButton)
        }
        
        view.addSubview(instrumentBgView)
        instrumentBgView.snp.makeConstraints { make in
            make.right.equalTo(-15)
            make.size.equalTo(95)
            make.top.equalTo(beatBgView)
        }
        
        instrumentBgView.addSubview(insctrumentButton)
        insctrumentButton.snp.makeConstraints { make in
            make.height.equalTo(30)
            make.left.equalTo(10)
            make.right.equalTo(-10)
            make.bottom.equalTo(-18)
        }
        
        view.addSubview(textFieldBgView)
        textFieldBgView.snp.makeConstraints { make in
            make.bottom.equalTo(40)
            make.height.equalTo(40)
            make.left.equalTo(20)
            make.right.equalTo(-20)
        }
        
        textFieldBgView.addSubview(textFieldConfirmButton)
        textFieldConfirmButton.snp.makeConstraints { make in
            make.right.equalTo(0)
            make.top.bottom.equalTo(0)
            make.width.equalTo(60)
        }
        
        textFieldBgView.addSubview(textField)
        textField.snp.makeConstraints { make in
            make.left.equalTo(20)
            make.centerY.equalToSuperview()
            make.right.equalTo(textFieldConfirmButton.snp.left).offset(-10)
        }
        
        textFieldConfirmButton.setContentCompressionResistancePriority(.required, for: .horizontal)
    }
    
    private func requestData() {
        AF.request(App.kAllMusic).response { [weak self] response in
            guard let `self` = self else { return }
            guard let data = response.data, let json = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] else {
                return
            }
            let result = json.compactMap({
                if let id = $0["id"] as? String, let filename = $0["filename"] as? String, let urlStr = $0["accessUrl"] as? String {
                    if let url = URL(string: urlStr) {
                        return Instrument(id: id, name: filename, url: url)
                    }
                    return nil
                }
                return nil
            })
            self.instruments = result
            self.setDefaultConfig()
        }
    }
    
    private func setDefaultConfig() {
        beatsCount = 4
        beatLeftValue = 4
        beatRightValue = 2
        currentTempo = 60
        showBeats(num: beatsCount)
        selectedInstrument = instruments.first
    }
    
    private func showBeats(num: Int) {
        guard num <= beatsView.count else { return }
        beatsCount = num
        let y: CGFloat = offsetY + 46
        let space: CGFloat = 10
        let itemWidth: CGFloat = (UIScreen.main.bounds.width - space) / CGFloat(num) - space
        let itemHeight: CGFloat = 130
        for i in 0..<beatsView.count {
            let v = beatsView[i]
            v.backgroundColor = UIColor(0xD3D0FB)
            v.layer.cornerRadius = min(12, itemWidth * 0.5)
            if i < num {
                v.isHidden = false
                v.frame = CGRect(x: space + CGFloat(i) * (itemWidth + space), y: y, width: itemWidth, height: itemHeight)
            } else {
                v.isHidden = true
            }
        }
    }
    
    @objc private func onClickBeatButton(_ sender: UIButton) {
        textField.resignFirstResponder()
        let vc = BeatSelectorViewController(left: "\(beatLeftValue)", right: "\(beatRightValue)")
        vc.onSubmit = { [weak self] (left, right) in
            self?.beatLeftValue = Int(left) ?? 2
            self?.beatRightValue = Int(right) ?? 1
        }
        self.navigationController?.present(vc, animated: true)
    }
    
    @objc private func onClickTempoButton(_ sender: UIButton) {
        textField.becomeFirstResponder()
    }
    
    @objc private func onClickJianTempoButton(_ sender: UIButton) {
        textField.resignFirstResponder()
        if currentTempo > 0 {
            currentTempo -= 1
        }
    }
    
    @objc private func onClickJiaTempoButton(_ sender: UIButton) {
        textField.resignFirstResponder()
        if currentTempo < 200 {
            currentTempo += 1
        }
    }
    
    @objc private func onClickInstrumentButton(_ sender: UIButton) {
        textField.resignFirstResponder()
        guard instruments.count > 0 else { return }
        let ins = selectedInstrument ?? instruments[0]
        let vc = InstrumentsSelectorViewController(instruments: instruments, selected: ins)
        vc.onSubmit = { [weak self] ins in
            self?.selectedInstrument = ins
        }
        navigationController?.present(vc, animated: true)
    }
    
    @objc private func onClickStartButton(_ sender: UIButton) {
        textField.resignFirstResponder()
        sender.isSelected = !sender.isSelected
        if sender.isSelected {
            startTimer()
        } else {
            stopTimer()
        }
    }
    
    @objc private func onClickTextFieldConfirmButton(_ sender: UISwitch) {
        textField.resignFirstResponder()
        guard let value = Int(textField.text ?? "0") else { return }
        currentTempo = value
    }
    
    private func startTimer() {
        timeCounter = -1
        timer?.pause()
        timer = nil
        let t = ZZTimer(.main)
        let duration = Double(60) / Double(currentTempo)
        t.scheduled(repeat: duration, qos: .default) { [weak self] in
            self?.timerAction()
        }
        timer = t
        t.fire()
    }
    
    private func stopTimer() {
        timer?.pause()
    }
    
    private func timerAction() {
        timeCounter += 1
        let idx = timeCounter % beatsCount
        for i in 0..<beatsView.count {
            if i == idx {
                beatsView[i].backgroundColor = UIColor(0xE6D5A1)
            } else {
                beatsView[i].backgroundColor = UIColor(0xD3D0FB)
            }
        }
        player.seek(to: .zero)
        if idx == 0 {
            player.volume = 1.0
        } else {
            player.volume = 0.5
        }
        player.play()
    }
    
    @objc func keyboardWillShow(_ notification: Notification) {
        if let userInfo = notification.userInfo,
           let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
            // Adjust bottom constraint based on keyboard height
            let keyboardHeight = keyboardFrame.height
            textFieldBgView.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight - 40)
        }
    }

    @objc func keyboardWillHide(_ notification: Notification) {
        textFieldBgView.transform = CGAffineTransform.identity
    }
}

extension JiepaiViewController: UITextFieldDelegate {
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if !string.isEmpty {
            let str = NSString(string: "0123456789")
            if str.range(of: string).length == 0 {
                return false
            }
            let old = textField.text ?? ""
            if old == "0" && !string.isEqual("0") {
                textField.text = string
                return false
            }
        }
        let currentText = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) ?? string
        let value = Int(currentText) ?? 0
        if value > 200 {
            return false
        }
        return true
    }
}
